package com.lanyun.aicorrectassistant.domain.assignmentTemplates.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.OSSObject;
import com.lanyun.aicorrectassistant.basic.entity.AssignmentTemplates;
import com.lanyun.aicorrectassistant.basic.entity.AuthUser;
import com.lanyun.aicorrectassistant.basic.entity.StudentAssignments;
import com.lanyun.aicorrectassistant.basic.service.AssignmentTemplatesService;
import com.lanyun.aicorrectassistant.basic.service.AuthUserService;
import com.lanyun.aicorrectassistant.basic.service.StudentAssignmentsService;
import com.lanyun.aicorrectassistant.config.StorageConfig;
import com.lanyun.aicorrectassistant.context.LoginContextHolder;
import com.lanyun.aicorrectassistant.controller.admin.assignmentTemplates.vo.AssignmentTemplatesRequestPageVO;
import com.lanyun.aicorrectassistant.controller.admin.assignmentTemplates.vo.AssignmentTemplatesRequestVO;
import com.lanyun.aicorrectassistant.controller.admin.assignmentTemplates.vo.AssignmentTemplatesResponseVO;
import com.lanyun.aicorrectassistant.convert.AssignmentTemplatesConvert;
import com.lanyun.aicorrectassistant.domain.assignmentTemplates.AssignmentTemplatesDomainService;
import com.lanyun.aicorrectassistant.basic.bean.PageResult;
import com.lanyun.aicorrectassistant.enums.AssignmentEnum;
import com.lanyun.aicorrectassistant.enums.IsDeletedFlagEnum;
import com.lanyun.aicorrectassistant.enums.RoleTypeEnum;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.output.Response;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 作业模板表领域服务实现
 *
 * @author makejava
 * @version 1.0
 * @date 2025-05-12 01:52:18
 */
@Service
@Slf4j
public class AssignmentTemplatesDomainServiceImpl implements AssignmentTemplatesDomainService {

    @Resource
    private AssignmentTemplatesService assignmentTemplatesService;

    @Resource
    private OSS ossClient;

    @Resource
    private StorageConfig storageConfig;

    @Resource
    private StreamingChatLanguageModel qwenModel;

    @Resource
    private ChatLanguageModel chatLanguageModel;

    @Resource
    private StudentAssignmentsService studentAssignmentsService;

    @Resource
    private AuthUserService authUserService;

    @Override
    public PageResult<AssignmentTemplatesResponseVO> page(AssignmentTemplatesRequestPageVO requestPageVO) {
        PageResult<AssignmentTemplatesResponseVO> pageResult = new PageResult<>();
        AssignmentTemplates queryEntity = AssignmentTemplatesConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        List<AssignmentTemplates> entities = assignmentTemplatesService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = assignmentTemplatesService.count(queryEntity);
        List<AssignmentTemplatesResponseVO> vos = AssignmentTemplatesConvert.INSTANCE.convertEntityToRespList(entities);

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    public Boolean update(AssignmentTemplatesRequestVO requestVO) {
        AssignmentTemplates entity = AssignmentTemplatesConvert.INSTANCE.convert(requestVO);
        return assignmentTemplatesService.update(entity) != 0;
    }

    @Override
    public Boolean delete(Long id) {
        AssignmentTemplates entity = new AssignmentTemplates();
        entity.setId(id);
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return assignmentTemplatesService.update(entity) != 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(AssignmentTemplatesRequestVO requestVO) {
        AssignmentTemplates entity = AssignmentTemplatesConvert.INSTANCE.convert(requestVO);
        Long teacherId = parseTeacherIdSafely(LoginContextHolder.getLoginId());
        entity.setTeacherId(teacherId);
        entity.setCreateTime(new Date());
        entity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        assignmentTemplatesService.insert(entity);

        // 查询所有学生用户
        List<AuthUser> authUsers = getActiveStudents();
        if (authUsers.isEmpty()) {
            return true;
        }

        // 批量创建学生作业并插入
        List<StudentAssignments> assignments = createStudentAssignments(entity, authUsers);
        studentAssignmentsService.batchInsert(assignments);

        return true;
    }

    // 安全解析教师ID
    private Long parseTeacherIdSafely(String loginId) {
        try {
            return Long.valueOf(loginId);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid teacher ID format", e);
        }
    }

    // 获取所有活跃学生
    private List<AuthUser> getActiveStudents() {
        AuthUser query = new AuthUser();
        query.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        query.setRole(RoleTypeEnum.STUDENT.getRole());
        return authUserService.queryAllByCondition(query);
    }

    // 创建学生作业列表
    private List<StudentAssignments> createStudentAssignments(AssignmentTemplates template, List<AuthUser> students) {
        Date now = new Date();
        return students.stream()
                .map(student -> buildStudentAssignment(template, student, now))
                .collect(Collectors.toList());
    }

    // 构建单个学生作业对象
    private StudentAssignments buildStudentAssignment(AssignmentTemplates template, AuthUser student, Date createTime) {
        StudentAssignments assignment = new StudentAssignments();
        assignment.setStudentId(student.getId());
        assignment.setTemplateId(template.getId());
        assignment.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        assignment.setStatus(AssignmentEnum.WAIT.getCode());
        assignment.setCreateTime(createTime);
        assignment.setAiThinkingProcess(template.getAiThinkingProcess());
        return assignment;
    }

    @Override
    public AssignmentTemplatesResponseVO get(Long id) {
        AssignmentTemplates entity = assignmentTemplatesService.queryById(id);
        return AssignmentTemplatesConvert.INSTANCE.convert(entity);
    }

//    @Override

    /// /    public Flux<String> generateAIThinkingProcess(AssignmentTemplatesRequestVO requestVO) throws Exception {
    /// /        String content = readDocument(requestVO.getFilePath());
    /// /
    /// /        String fullPrompt = buildPrompt(content, requestVO);
    /// /
    /// /        return callQwenModel(fullPrompt);
    /// /    }

    public String generateAIThinkingProcess(AssignmentTemplatesRequestVO requestVO) throws Exception {
        String content = readDocument(requestVO.getFilePath());

        String fullPrompt = buildPrompt(content, requestVO);

        String result = callQwenModel(fullPrompt);

        return result;
    }

    private String readDocument(String uri) throws Exception {
        if (uri.startsWith("http")) {
            return readOSSDocument(uri);
        } else {
            return readLocalDocument(uri);
        }
    }

    // 读取OSS文档
    private String readOSSDocument(String objectUrl) throws Exception {
        String objectName = extractObjectName(objectUrl);

        try (OSSObject ossObject = ossClient.getObject(
                storageConfig.getAliyunOss().getBucketName(),
                objectName);
             InputStream contentStream = ossObject.getObjectContent();
             XWPFDocument document = new XWPFDocument(contentStream);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {

            return extractor.getText();
        }
    }

    private String readLocalDocument(String filePath) throws Exception {
        try (FileInputStream fis = new FileInputStream(filePath);
             XWPFDocument document = new XWPFDocument(fis);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {

            return extractor.getText();
        }
    }

    // URL解析优化
    private String extractObjectName(String url) throws UnsupportedEncodingException, URISyntaxException {
        String decodedUrl = URLDecoder.decode(url, StandardCharsets.UTF_8);
        URI uri = new URI(decodedUrl);
        String path = uri.getPath();
        return path.startsWith("/") ? path.substring(1) : path;
    }

    // 构建提示词模板
    private String buildPrompt(String content, AssignmentTemplatesRequestVO requestVO) {
        return String.format(
                "作为专业教育助手，请根据以下要素生成阅卷思路：\n" +
                        "1. 作业核心内容：\n" +
                        "%s\n" +
                        "2. 教师特别要求：%s\n" +
                        "请按以下要求生成：\n" +
                        "- 不需要使用Markdown格式回复，如果要换行则回复换行符\n" +
                        "- 包含评分标准制定步骤\n" +
                        "- 突出显示重点检查方向\n" +
                        "- 预测可能出现的错误类型",
                content,
                requestVO.getFocusDirections().replace("\"", "\\\"")
        );
    }

    // 调用Qwen模型
//    private Flux<String> callQwenModel(String prompt) {
//        return Flux.create(sink -> {
//            qwenModel.chat(prompt, new StreamingChatResponseHandler() {
//                @Override
//                public void onPartialResponse(String partialResponse) {
//                    sink.next(partialResponse);
//                }
//
//                @Override
//                public void onCompleteResponse(ChatResponse chatResponse) {
//                    sink.complete();
//                }
//
//                @Override
//                public void onError(Throwable throwable) {
//                    sink.error(throwable);
//                }
//            });
//        });
//    }

    private String callQwenModel(String prompt) {
        String chat = chatLanguageModel.chat(prompt);
        return chat;
    }

}
